package com.gis3c.ol.web.controller;

import com.gis3c.ol.entity.Layer;
import com.gis3c.ol.entity.Map;
import com.gis3c.ol.entity.MapLayer;
import com.gis3c.ol.entity.Source;
import com.gis3c.ol.service.LayerService;
import com.gis3c.ol.service.MapService;
import com.gis3c.ol.service.SourceService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.ArrayStack;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * Created by hukekuan on 2017/12/14.
 */
@Controller
@RequestMapping(value = "/ol")
public class ClientController {
    @Autowired
    private MapService mapService;
    @Autowired
    private LayerService layerService;
    @Autowired
    private SourceService sourceService;

    @RequestMapping(value = "/test")
    public String test(){
        return "test";
    }

    //    ==========================================应用管理===============================================
    @RequestMapping(value = "/map/mapinit")
    @ResponseBody
    public Object mapInit(@RequestParam(value = "mapid") String mapId){
        java.util.Map<String,Object> result = new HashMap<>();
        Map queryMap = mapService.findMapById(mapId);
        String[] layerIdArray;
        if(queryMap != null){
            result.put("map",queryMap);
            layerIdArray = queryMap.getLayers();
            result.put("layer",layerService.findLayerByIds(layerIdArray));
        }
        return result;
    }

    @RequestMapping("/mapmanage")
    public String mapManage() {
        return "ol/mapmanage";
    }

    @RequestMapping("/maplist")
    @ResponseBody
    public Object MapList(
            @RequestParam(value = "limit", required = true) Integer pageSize,
            @RequestParam(value = "page", required = true) Integer currentPage) {
        java.util.Map<String, Object> result = new HashMap<>();
        List<java.util.Map<String, Object>> mapList = mapService.findMapsByPage(pageSize, currentPage);
        result.put("count", mapService.findMapCount());
        result.put("data", mapList);
        result.put("code", 0);
        result.put("msg", "");
        return result;
    }

    @RequestMapping(value = "/mapadd")
    public String mapAdd() {
        return "ol/mapedit";
    }

    @RequestMapping(value = "/mapcreate", method = RequestMethod.POST)
    @ResponseBody
    public Object mapCreate(@ModelAttribute("map") Map map) {
        java.util.Map<String, Object> result = new HashMap<>();
        if (map != null) {
            if (map.getView() != null) {
                if (map.getView().containsKey("center")) {
                    String[] centerArray = map.getView().get("center").toString().split(",");
                    map.getView().put("center", Arrays.asList(new Double[]{
                            Double.parseDouble(centerArray[0]),
                            Double.parseDouble(centerArray[1])
                    }));
                }
                if (map.getView().containsKey("zoom")) {
                    map.getView().put("zoom", Integer.parseInt(map.getView().get("zoom").toString()));
                }
                if (map.getView().containsKey("maxZoom")) {
                    map.getView().put("maxZoom", Integer.parseInt(map.getView().get("maxZoom").toString()));
                }
                if (map.getView().containsKey("minZoom")) {
                    map.getView().put("minZoom", Integer.parseInt(map.getView().get("minZoom").toString()));
                }
            }

            mapService.insertMap(map);
            result.put("status", "OK");
            return result;
        }
        result.put("status", "error");
        return result;
    }

    @RequestMapping(value = "/mapremove", method = RequestMethod.POST)
    @ResponseBody
    public Object mapDelete(@RequestBody String mapIds) {
        java.util.Map<String, Object> result = new HashMap<>();
        Set<String> idSet = new HashSet<>(Arrays.asList(mapIds.split(",")));
        Integer deleteSize = mapService.deleteMapsById(idSet);

        if(deleteSize.equals(idSet.size())){
            result.put("status", "OK");
        }else{
            result.put("status", "error");
        }
        return result;
    }

    @RequestMapping(value = "/map/layerbindpage",method = RequestMethod.GET)
    public String layerBindPage(@RequestParam(value = "mapid", required = true) String mapId,Model model){
        model.addAttribute("mapId",mapId);
        return "ol/layerbind";
    }

    @RequestMapping(value = "/map/mapentry",method = RequestMethod.GET)
    @ResponseBody
    public Object mapEntry(@RequestParam(value = "mapid", required = true) String mapId){
        return mapService.findMapById(mapId);
    }

    @RequestMapping(value = "/map/layerlist", method = RequestMethod.GET)
    @ResponseBody
    public Object layerListForMap(@RequestParam(value = "mapid", required = true) String mapId){
        java.util.Map<String,Object> result = new HashMap<>();
        Map queryMap = mapService.findMapById(mapId);
        result.put("layer",layerService.findSimpleLayerList());
        result.put("mapLayers",queryMap == null ? new ArrayList<String>():queryMap.getLayers());
        return result;
    }

    @RequestMapping(value = "/map/layerbind",method = RequestMethod.POST)
    @ResponseBody
    public Object layerBind(@RequestBody(required = true) java.util.Map<String,Object> bindingLayer){
        java.util.Map<String, Object> result = new HashMap<>();

        if(bindingLayer.containsKey("mapId") && bindingLayer.containsKey("layerIds")){
            Integer integer = mapService.bindLayer(bindingLayer.get("mapId").toString(), ((List<String>) bindingLayer.get("layerIds")).toArray(new String[0]));
            if(integer > 0){
                result.put("status", "OK");
            }else{
                result.put("status", "error");
            }
        }else {
            result.put("status", "error");
        }

        return result;
    }

    //    ==========================================图层管理===============================================
    @RequestMapping("/layer/layermanage")
    public String layerManage() {
        return "ol/layermanage";
    }

    @RequestMapping("/layer/layerlist")
    @ResponseBody
    public Object layerList(
            @RequestParam(value = "limit", required = true) Integer pageSize,
            @RequestParam(value = "page", required = true) Integer currentPage) {
        java.util.Map<String, Object> result = new HashMap<>();
        List<java.util.Map<String, Object>> layerList = layerService.findLayersByPage(pageSize, currentPage);
        result.put("count", layerService.findLayerCount());
        result.put("data", layerList);
        result.put("code", 0);
        result.put("msg", "");
        return result;
    }

    @RequestMapping(value = "/layer/layeradd")
    public String layerAdd(@RequestParam(value = "type", required = false) String type, Model model) {
        model.addAttribute("type",type);
        return "ol/layeredit";
    }

    @RequestMapping(value = "/layer/layercreate", method = RequestMethod.POST)
    @ResponseBody
    public Object layerCreate(@ModelAttribute("layer") Layer layer) {
        java.util.Map<String, Object> result = new HashMap<>();
        if (layer != null) {
            layerService.insertLayer(layer);
            result.put("status", "OK");
            return result;
        }
        result.put("status", "error");
        return result;
    }

    @RequestMapping(value = "/layer/layerremove", method = RequestMethod.POST)
    @ResponseBody
    public Object layerDelete(@RequestBody(required = true) String layerIds) {
        java.util.Map<String, Object> result = new HashMap<>();
        Set<String> idSet = new HashSet<>(Arrays.asList(layerIds.split(",")));
        Integer deleteSize = layerService.deleteLayersById(idSet);

        if(deleteSize.equals(idSet.size())){
            result.put("status", "OK");
        }else{
            result.put("status", "error");
        }
        return result;
    }

    @RequestMapping(value = "/layer/sourcebindpage",method = RequestMethod.GET)
    public String sourceBindPage(@RequestParam(value = "layerid", required = true) String layerId,Model model){
        Layer queryLayer = layerService.findeLayerById(layerId);
        model.addAttribute("layerId",queryLayer.getLayerId());
        model.addAttribute("type",queryLayer.getType());
        model.addAttribute("opacity",queryLayer.getOpacity());
        model.addAttribute("extent",queryLayer.getExtent());

        model.addAttribute("options", JSONObject.fromObject(queryLayer.getOptions()));
        return "ol/sourcebind";
    }

    @RequestMapping(value = "/layer/sourcelist",method = RequestMethod.GET)
    @ResponseBody
    public Object sourceList(@RequestParam(value = "layerid", required = true) String layerId){
        Optional<Layer> queryLayer = Optional.ofNullable(layerService.findeLayerById(layerId));
        String sourceId = queryLayer
                .map(layer -> layer.getSource())
                .orElse("");
        List<Source> sourceList = sourceService.findSourceByType(
                queryLayer
                        .map(layer -> layer.PossibleSourceType())
                        .orElse(new String[]{}),
                queryLayer
                        .map(layer -> layer.getProjection())
                        .orElse("")
        );

        List<java.util.Map<String,Object>> resultSourceList = new ArrayList<>();
        java.util.Map<String,Object> resultSource;
        for(Source source : sourceList){
            resultSource = new HashMap<>();
            resultSource.put("sourceId",source.getSourceId());
            resultSource.put("sourceName",source.getSourceName());
            if(sourceId.equals(source.getSourceId())){
                resultSource.put("LAY_CHECKED",true);
            } else {
                resultSource.put("LAY_CHECKED",false);
            }

            resultSourceList.add(resultSource);
        }

        return resultSourceList;
    }

    @RequestMapping(value = "/layer/sourcebind",method = RequestMethod.POST,consumes = "application/json")
    @ResponseBody
    public Object sourceBind(@RequestBody(required = true) java.util.Map<String,Object> bindData){
        java.util.Map<String, Object> result = new HashMap<>();

        if(bindData.containsKey("layerId") && bindData.containsKey("sourceId")){
            Integer updateCount = layerService.bindSource(
                    bindData.get("layerId").toString(),
                    bindData.get("sourceId").toString(),
                    bindData.containsKey("options")? (java.util.Map<String, Object>) bindData.get("options") :null
            );
            if(updateCount == 1){
                result.put("status", "OK");
            }else {
                result.put("status", "error");
            }
        }else {
            result.put("status", "error");
        }
        return result;
    }

    @RequestMapping(value = "/layer/layerentry",method = RequestMethod.GET)
    @ResponseBody
    public Object findLayerById(@RequestParam(value = "layerid", required = true) String layerId){
        java.util.Map<String,Object> result = new HashMap<>();
        Layer queryLayer = layerService.findeLayerById(layerId);
        String sourceId = queryLayer == null ? "":queryLayer.getSource();
        result.put("layer",queryLayer);
        if(sourceId != null && !"".equals(sourceId)){
            result.put("source",sourceService.findSourceById(sourceId));
        }

        return result;
    }

    @RequestMapping(value = "/layer/layerentries",method = RequestMethod.GET)
    @ResponseBody
    public Object findLayerByIds(@RequestParam(value = "layerids", required = true) String layerIds){
        String[] layerIdArray = layerIds.split(",");
        return layerService.findLayerByIds(layerIdArray);
    }
    //    ==========================================数据源管理===============================================
    @RequestMapping("/sourcemanage")
    public String SourceManage() {
        return "ol/sourcemanage";
    }

    @RequestMapping("/sourcelist")
    @ResponseBody
    public Object SourceList(
            @RequestParam(value = "limit", required = true) Integer pageSize,
            @RequestParam(value = "page", required = true) Integer currentPage) {
        java.util.Map<String, Object> result = new HashMap<>();
        List<java.util.Map<String, Object>> sourceList = sourceService.findSourcesByPage(pageSize, currentPage);
        result.put("count", sourceService.findSourceCount());
        result.put("data", sourceList);
        result.put("code", 0);
        result.put("msg", "");
        return result;
    }

    @RequestMapping(value = "/source/sourceentry", method = RequestMethod.GET)
    @ResponseBody
    public Object findSourceById(@RequestParam(value = "sourceid", required = true)String sourceId){
        return sourceService.findSourceById(sourceId);
    }

    @RequestMapping(value = "/sourceadd", method = RequestMethod.GET)
    public String sourceAdd(@RequestParam(value = "type", required = false) String type, Model model) {
        model.addAttribute("type",type);
        return "ol/sourceedit";
    }

    @RequestMapping(value = "/sourcecreate", method = RequestMethod.POST)
    @ResponseBody
    public Object sourceCreate(@ModelAttribute("source") Source source) {
        java.util.Map<String, Object> result = new HashMap<>();
        if (source != null) {
            sourceService.insertSource(source);
            result.put("status", "OK");
            return result;
        }
        result.put("status", "error");
        return result;
    }

    @RequestMapping(value = "/sourceremove", method = RequestMethod.POST)
    @ResponseBody
    public Object sourceDelete(@RequestBody String sourceIds) {
        java.util.Map<String, Object> result = new HashMap<>();
        Set<String> idSet = new HashSet<>(Arrays.asList(sourceIds.split(",")));
        Integer deleteSize = sourceService.deleteSourcesById(idSet);
        if(deleteSize.equals(idSet.size())){
            result.put("status", "OK");
        }else{
            result.put("status", "error");
        }

        return result;
    }

    /**
     * 数据源编辑页面
     * @param sourceId
     * @param model
     * @return
     */
    @RequestMapping(value = "/sourceeditpage", method = RequestMethod.GET)
    public String sourceEditPage(@RequestParam(value = "sourceid", required = true) String sourceId, Model model) {
        Source editedSource = sourceService.findSourceById(sourceId);
        model.addAttribute("source",editedSource);
        model.addAttribute("type",editedSource.getType());
        return "ol/sourceedit";
    }

    @RequestMapping(value = "/sourceedit", method = RequestMethod.POST)
    @ResponseBody
    public Object sourceEdit(@ModelAttribute("source") Source source) {
        java.util.Map<String, Object> result = new HashMap<>();
        if (source != null) {
            sourceService.updateSource(source);
            result.put("status", "OK");
            return result;
        }
        result.put("status", "error");
        return result;
    }
}
